---
menu: Active Proposals
name: Menu Elements (Explainer)
path: /components/menu.explainer
layout: ../../layouts/ComponentLayout.astro
---

- Authors: [@domfarolino](https://github.com/domfarolino), [@dizhang168](https://github.com/dizhang168), [@josepharhar](https://github.com/josepharhar), [@mfreed7](https://github.com/mfreed7)

{/* START doctoc generated TOC please keep comment here to allow auto update */}
{/* DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE */}

## Table of Contents

- [Table of Contents](#table-of-contents)
- [Introduction](#introduction)
- [Examples & code snippets](#examples--code-snippets)
- [The `<menubar>` element](#the-menubar-element)
- [The `<menulist>` element](#the-menulist-element)
- [The `<menuitem>` element](#the-menuitem-element)
- [Invoking a `<menulist>` from a `<button>`](#invoking-a-menulist-from-a-button)
- [Accessibility](#accessibility)
- [General questions](#general-questions)
- [Examples in code](#examples-in-code)
- [Future enhancements](#future-enhancements)
- [Reading List](#reading-list)
- [Issues / Discussions](#issues--discussions)

## Introduction

An application menu is a common way to group actions together in the form of menu items, and provide
users the ability to execute commands.

This proposal introduces the `<menubar>`, `<menulist>`, and `<menuitem>` elements to support
application menus on the web. These menus will:

 - Represent commands as `<menuitem>`s, grouped together in a `<menulist>` popover or in-page
   `<menubar>`.
 - Represent state in checkable and radio-style menu items.
 - Provide the correct implicit ARIA roles and keyboard interaction model out of the box.
 - Give web developers default styles that create functional menus without having to re-invent
   common popover and anchor positioning patterns, or re-implement ARIA patterns.

Note that this explainer only covers application menus, not navigation menus, which is a different
pattern covered by a different (as yet unpublished) proposal altogether.

## Examples & code snippets

The goal of our proposal is to make it easy for web developers to author accessible menus with very
little markup and JavaScript. Consider the following examples:

<img width="400" src="/images/menu-elements-example-1.png" alt="menu elements expanded showing commands" />

```html
<menubar>
  <menuitem commandfor="file-menu" command="toggle-menu">File</menuitem>
  <menuitem commandfor="edit-menu" command="toggle-menu">Edit</menuitem>
  <menuitem commandfor="view-menu" command="toggle-menu">View</menuitem>
  <menuitem commandfor="help-menu" command="toggle-menu">Help</menuitem>
</menubar>

<!-- File Menu (Level 1) -->
<menulist id="file-menu">
  <menuitem>New</menuitem>
  <!-- This item triggers a nested submenu (Level 2) -->
  <menuitem commandfor="open-recent-menu" command="toggle-menu">Open Recent</menuitem>
  <hr>
  <menuitem>Save</menuitem>
  <menuitem>Save As...</menuitem>
  <menuitem disabled>Print</menuitem>
  <hr>
  <menuitem>Exit</menuitem>
</menulist>

<!-- Open Recent Menu (Level 2) -->
<menulist id="open-recent-menu">
  <menuitem>Document1.txt</menuitem>
  <menuitem>Report.docx</menuitem>
  <menuitem>Spreadsheet.xlsx</menuitem>
  <hr>
  <menuitem>Clear List</menuitem>
</menulist>
```

<br/>
<br/>

<img width="400" src="/images/menu-elements-example-2.png" alt="menu elements expanded showing checkable state" />

```html
<menubar>
  <menuitem commandfor="file-menu" command="toggle-menu">File</menuitem>
  <menuitem commandfor="edit-menu" command="toggle-menu">Edit</menuitem>
  <menuitem commandfor="view-menu" command="toggle-menu">View</menuitem>
  <menuitem commandfor="help-menu" command="toggle-menu">Help</menuitem>
</menubar>

<!-- View Menu (Level 1) -->
<menulist id="view-menu">
  <!-- This item triggers a nested submenu (Level 2) -->
  <menuitem commandfor="zoom-menu" command="toggle-menu">Zoom</menuitem>
  <menuitem>Full Screen</menuitem>
  <hr>
  <fieldset checkable="multiple">
    <menuitem defaultchecked>Show Ruler</menuitem>
    <menuitem>Show Outline</menuitem>
    <menuitem defaultchecked>Show Comments</menuitem>
  </fieldset>
</menulist>

<!-- Zoom Menu (Level 2) -->
<menulist id="zoom-menu">
  <fieldset checkable="single">
    <menuitem>50%</menuitem>
    <menuitem>75%</menuitem>
    <menuitem defaultchecked>100%</menuitem>
    <menuitem>150%</menuitem>
    <menuitem>200%</menuitem>
  </fieldset>
</menulist>
```

*These images were captured using [our test site](https://jsbin.com/vawevuc/edit?html,output) to
test and demo these new elements.*

Because new elements in the markup above build off of existing features such as the [Popover
API](https://open-ui.org/components/popover.research.explainer/), [Invoker
Commands](https://open-ui.org/components/invokers.explainer/), and [CSS anchor
positioning](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_anchor_positioning), much of the
behaviors needed by the menu use case are provided natively, and do not need to be re-invented by
web developers or library authors.

Further, these elements will have the correct implicit ARIA roles, states, and properties, as well
as a keyboard interaction & focus model that users expect.

## The `<menubar>` element

The `<menubar>` element represents an in-page group of `<menuitem>` elements that can either invoke
commands or open submenus of commands. It defaults to a horizontal orientation, and its child
`<menuitem>` elements are flex items displayed in a row.

This element:

* Provides the implicit [`menubar`](https://w3c.github.io/aria/#menubar) ARIA role.
* Provides the correct keyboard and focus behavior across child menu items and
  sub menulists.

**Content model**: the `<menubar>` element allows the following elements as descendants:
* `<menuitem>`
* Anchor `<a>` tags are disallowed in menu bars, due to accessibility concerns around exposing
  links in ARIA menus, and concerns around the navigation menubar pattern. We enforce this with the
  content model, and propose default `display: none` styles for anchors that are descendants of
  `<menubar>` elements.


## The `<menulist>` element

The `<menulist>` element is another way to group `<menuitem>`s together. This element is a native
**popover**, and must be invoked by a button or a `<menuitem>` to show what it represents—a stack
of `<menuitem>`s with default styles that resemble an application drop-down menu.

This element:

* Provides the implicit [`menu`](https://w3c.github.io/aria/#menu) ARIA role.
* Has default anchor positioning styles that anchor it to its
  [implicit anchor](https://drafts.csswg.org/css-anchor-position/#implicit-anchor-element)—the
  button or menuitem that invoked it.
* Supports the `:popover-open` pseudo-class, as it is a native **popover**.
* Supports the
  [`toggle` event](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/toggle_event), as it
  is a native **popover**.
* Can be invoked with the new `show-menu` command, and is referenced by its ID from its invoker.
* Provides the correct keyboard and focus behavior across sub-menulists, menubars, and child menu
  items.

**Content model**: the `<menulist>` element allows the following elements as descendants:

* `<menuitem>`
* `<hr>`
* `<fieldset>`
* **Interactive content**: When interactive content appears in a menu, it will be a sibling of
  `<menuitem>`s, not nested inside them, as nested interactive content is generally inaccessible.
  See [Issue #1323](https://github.com/openui/open-ui/issues/1323) for more discussion on how we
  might support other interactive content in menus, such as `<input type=search>`.
* Anchor `<a>` tags are disallowed in menu lists, due to accessibility concerns around exposing
  links in ARIA menus, and concerns around the navigation menubar pattern. We enforce this with the
  content model, and propose default `display: none` styles for anchors that are direct descendants
  of `<menulist>` elements.

The `<fieldset>` element is used in a `<menulist>` to group menu items that serve a common purpose.
It gives two key pieces of functionality:

* Captioned groups, with its optional `<legend>` for labeling.
* A common ancestor for checkable `<menuitem>`s. This supports both exclusively checkable and
  multi-checkable menu items.

**Checkable menu items**

To support checkable menu items, we propose the new `checkable` **content** attribute on
`<fieldset>`, reflected by a corresponding boolean **IDL** attribute, to group items as either
radios or checkboxes; its allowed values are `checkable=single` and `checkable=multiple`:

```html
<menulist id=sort-menu>
  <fieldset checkable=single>
    <legend>Sort by</legend>
    <menuitem>Recently added</menuitem>
    <menuitem>Date created</menuitem>
    <menuitem>Creator</menuitem>
  </fieldset>

  <fieldset checkable=multiple>
    <menuitem>1 bedroom</menuitem>
    <menuitem>2 bedrooms</menuitem>
    <menuitem>3 bedrooms</menuitem>
  </fieldset>
</menulist>
```

Note that `<fieldset>` is totally optional—it is only needed to support captioned or checkable menu
items. If `<menuitem>`s appear bare in a `<menulist>` or `<menubar>` without a `<fieldset>`, then
they are just grouped together under their parent list or bar, but are logically separate and not
checkable.

## The `<menuitem>` element

Activating the `<menuitem>` element is how users invoke actions from an application menu. As
discussed, these can appear in `<menubar>` or `<menulist>` elements, and are used to invoke
commands, track checkable state, or open submenus with more menu items.

This element:

* Provides the implicit [`menuitem`](https://w3c.github.io/aria/#menu) ARIA role.
    * See "checkability" below for how this can change
* Provides the correct keyboard and focus behavior across sub-menulists, menubars, and sibling menu
  items.
* Has `command/commandfor` attributes to invoke sub-menus or issue other commands.
* Has a `disabled` **IDL** attribute and corresponding **content** attribute.
* Supports the `:enabled` and `:disabled` CSS pseudo-classes.
* Events:
    * Either a `change` or `checked` event will be fired on checkable menu items that have their
      state changed. See [Issue #1321](https://github.com/openui/open-ui/issues/1321).
    * A `click` event is fired upon activation. See
      [Issue #1312](https://github.com/openui/open-ui/issues/1312). Firing a synthetic `click` here
      is consistent with the
      [HTML Standard's prose on activation](https://html.spec.whatwg.org/C#activation).
* Checkability:
    * Supports checkability, by being contained in a `<fieldset checkable=single|multiple>`.
    * Has a `checked` boolean **IDL** attribute that does NOT reflected any content attribute, to
      track live-checked-ness.
    * Has a `defaultchecked` **content** attribute reflected by a `defaultChecked` boolean **IDL**
      attribute to cover checked initial-ness. See
      [Issue #1205](https://github.com/openui/open-ui/issues/1205).
    * Supports the :checked CSS pseudo-class and ::checkmark CSS pseudo-element.
    * Provides the right implicit ARIA role, either
      [`menuitemcheckbox`](https://w3c.github.io/aria/#menuitemcheckbox) or
      [`menuitemradio`](https://w3c.github.io/aria/#menuitemradio), depending on the checkability
      enabled.

**Content model**:

Similarly to customizable select, we expect most content in a menu to be wrapped inside
`<menuitem>`. This includes non-interactive elements and design items such as logos, images, text.

See [Issue #1323](https://github.com/openui/open-ui/issues/1323) for more discussion on how we might
support other interactive content in menus alongside the `<menuitem>` element, such as `<input type=search>`.

<img src="/images/menubar-search-input.png" alt="menubar examples with search input as a sibling of menuitems" />

## Invoking a `<menulist>` from a `<button>`

The `<menulist>` popover element can be used without a menubar invoking it through a menuitem. It
can be invoked by any command invoker element, such as the `<button>` element. This is a pattern
commonly seen on sites that provide one-off drop-down menus or filter overlays.

Similarly, `<button>` elements that reveal menus are commonly used in tables/grids to allow for
adjustments to the presentation of the tabular data, or to edit or delete specific row or cell
content:

<img src="/images/menu-table-button.jpg" alt="a button invokes a menulist in a table column header, revealing the menuitems to resize, reorder or sort by the column of which it was invoked." />

Toolbars or other groupings of controls beyond menubars may include buttons that display a popover
list of actions that appear in a menulist:

<img src="/images/menu-youtube-button.jpg" alt="the youtube player consists of multiple buttons that invoke their own menulists. The settings button invokes a menulist allowing for the adjustment of quality, playback speed, toggling annotations and more." />

<img src="/images/menu-split-button.jpg" alt="the create new button in github's top bar invokes a menulist to add new or import a repository, create a new codepace or gist, or make a new orginization or project." />

Button elements outside the context of a `<menubar>` can invoke `<menulist>` elements to fulfill the
use cases above by leveraging the `command` and `commandfor` attributes, and the new menu (or
existing popover) commands.

```html
<button command=toggle-menu commandfor=menu>Actions</button>

<menulist id=menu>
  <menuitem>Foo</menuitem>
</menulist>
```

A button that invokes a menulist in this way would have an implicit `aria-haspopup=menu` property,
along with an impliict `aria-expanded` state, reflecting whether the menulist is rendered (expanded)
or not (collapsed). It would not have an implicit `aria-details` property. This is because unlike
other more generic popovers, keyboard focus should immediately move from the invoking button to the
first focusable element, or element with the autofocus attribute, of the rendered `<menulist>`.

## Accessibility

One goal of this proposal is to make the menu elements we propose accessible by default. To achieve
this in part, our proposal follows the
[ARIA Authoring Practices Guide on the Menu and Menubar pattern](https://www.w3.org/WAI/ARIA/apg/patterns/menubar/)
and best practices curated from accessibility experts as closely as possible; deviations are
discussed with accessibility experts and documented here to the best of our ability. This section
describes the concrete implications on our proposal.

### Native ARIA role mapping

 - The `<menubar>` element exposes the implicit ARIA
   [`menubar`](https://w3c.github.io/aria/#menubar) role.
 - The `<menulist>` element exposes the implicit ARIA
   [`menu`](https://w3c.github.io/aria/#menu) role.
 - The `<menuitem>` element exposes the implicit ARIA
   [`menuitem`](https://w3c.github.io/aria/#menuitem) role by default.

While the `<menuitem>` element's native ARIA role defaults to `menuitem`, it is responsive to
whether the element is embedded in a `<fieldset checkable=single|multiple>`. The
[`menuitemradio`](https://w3c.github.io/aria/#menuitemradio) role is exposed for items in a
`<fieldset checkable=single>`, and the
[`menuitemcheckbox`](https://w3c.github.io/aria/#menuitemcheckbox) role is exposed for items in a
`<fieldset checkable=multiple>`.

### Parent/child relationship in the accessibility tree via `aria-owns`

Menu lists and sub-menulists are not nested in the DOM, however we considered using `aria-owns`
natively to establish a parent-child relationship for these menus in the accessibility tree. This
was discussed in [Issue 1297](https://github.com/openui/open-ui/issues/1297), where we resolved
against doing this.

### ARIA attributes

 - [`aria-expanded`](https://w3c.github.io/aria/#aria-expanded)
    - The `<menuitem>` element's `aria-expanded` attribute reflects whether or not a popover invoked
      by the `<menuitem>` is expanded. This includes sub-menu `<menulist>` elements (invokeable via
      the `show-menu`, `toggle-menu`, and `hide-menu` commands), or other popovers unrelated to our
      proposal
 - [`aria-checked`](https://w3c.github.io/aria/#aria-checked)
    - For checkable `<menuitem>` element, the `aria-checked` attribute reflects whether their
      current [state](https://w3c.github.io/aria/#dfn-state) is checked
 - [`aria-disabled`](https://w3c.github.io/aria/#aria-disabled)
    - See [§ Soft disabling](#soft-disabling)

### Soft disabling

A `<menuitem disabled>` element will be marked as `aria-disabled=true`, however the element will
still be keyboard reachable and focusable, just not activatable. See [Issue
#1274](https://github.com/openui/open-ui/issues/1274) for more discussion.

### Keyboard behavior

See [§ What should the keyboard behavior be?](#what-should-the-key-board-behavior-be) for details.

### Navigation menubars

In short, there are longstanding accessibility issues with navigation menus and our proposal does
not support the navigation menubar use case or pattern. See both the
[§ How does this proposal relate to navigation
menus?](#how-does-this-proposal-relate-to-navigation-menus) section and [Issue
#1193](https://github.com/openui/open-ui/issues/1193) for more information.


## General questions

### What should the keyboard behavior be?

We propose the keyboard behavior as described in the table of the ARIA Authoring Practices Guide,
which is demonstrative of the keyboard expectations for how menus and menubars work in operating
systems.

* A menubar has a single tab stop.
* A menulist is invoked when its popovertarget (a menuitem or a button). Focus would automatically move to its first focusable child.
* Tab focus will not trigger the menuitem to get selected/checked, but only when an explicit Enter/choice happens.
* An explicit Enter/Space on a menuitem without popvertarget and inside a menulist will close that menulist.
* An explicit Enter/Space does not close the menulist if the menuitem selected has a popovertarget that gets triggered.
* An explicit ESC will close the current popover menulist that has focus and return focus to its invoking element (which may be a menuitem inside a menulist or a menubar; or is a button element).
* Arrow keyboard events will allow navigating between menuitems.

**Questions**
* Is there any case where tab will close a menulist? For example, when we move from the last `<menuitem>` in a `<menulist>` and are moving to the next `<menuitem>` in the `<menubar>`.
* Do we need special behavior for hot keys?

### Why not reuse the `<menu>` element?

The existing
[`<menu>` element](https://html.spec.whatwg.org/C#the-menu-element) nominally represents a "toolbar"
of commands, despite having no related implicit ARIA role, no native command-invoking behavior, and
no other menu, menubar, or toolbar behaviors or keyboard interactions. Rather, it is a `<ul>` with a
different name. Due to these legacy behaviors (or lack thereof), we opted to not modify it at all,
and instead introduce the new `<menubar>` and `<menulist>` elements. You can read more about what
the existing menu element is and isn't [here](https://www.scottohara.me/blog/2021/10/21/menu.html).

Our proposal does not modify this existing element or its processing model, although we could
consider an opt-in that gives the existing `<menu>` element all of the semantics proposed here, or
simply change its semantics and processing model when it contains a new `<menuitem>` element as a
child. See https://github.com/openui/open-ui/issues/1194 for more discussion.


### What's the difference between this and the `<toolbar>` proposal?

There is a lot of nuance between the various menu-adjacent patterns: menubar, navigation menu, and
toolbar. See [Issue #1188](https://github.com/openui/open-ui/issues/1188) for discussion about how
to better crystalize this distinction in this explainer.

In short, menu elements provide a hierarchical structure to represent application menus and their
commands—they're generally used to acccess settings and application-wide configuration tools.
Toolbars, on the other hand, provide quick, in-page access to commands pertaining to a specific
component that the user is interacting with, like style settings for a document. Toolbars can
contain a variety of controls, for example, buttons and
[comboboxes](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/) (which can also invoke menu lists).


### How best to represent checkable `<menuitem>`s?

As stated, our proposal introduces a single `<menuitem>` element to represent all menu items,
including checkable state-bearing ones. Instead of representing both checkable & non-checkable menu
items with a single element, we could:

* Add a `type` attribute to `<menuitem>`, giving: `<menuitem type=checkbox>` and
  `<menuitem type=radio>`.
    * When present, the element's `checked` and `defaultChecked` attribute would take effect, much
      like `HTMLInputElement#checked` does on *checkable* inputs (while doing nothing on
      non-checkable inputs like `<input type=date>`).
* Add a `checkable` IDL attribute on `<menuitem>`
    * This attribute would control whether the element can be checked.
    * It could be a boolean IDL attribute, or take one of two values `checkable=single|multiple`,
      for radios and checkboxes respectively.
* Introduce new `<menuitemcheckbox>` and `<menuitemradio>` elements
    * These represent ARIA roles, and could be exposed as elements, but it adds complexity to the
    * proposal without giving us any accessibility wins.

These alternatives are reasonable, but more complicated than our proposal of adding a
`checkable=single|multiple` attribute to `<fieldset>`. By modifying the menu item itself to make it
checkable, in order to support radio exclusivity you need a mechanism to group all menu items that
participate in the same exclusive group, which would probably be the `name` attribute. Then, in
order to create a group of radio exclusive menu items, you either have to set two attributes instead
of one, or remember to use a new element and a new attribute.


### Is `<fieldset>` necessary to group `<menuitem>`s together?

We considered using the [`name`](https://html.spec.whatwg.org/C#attr-fe-name) attribute to group
exclusively checkable menu items, however it is confusing to use a form control attribute in this
setting which is distinct from forms altogether.

Further, if we want to support captioned / labeled groups of menu items, the `name` attribute
wouldn't be sufficient. So if we used the `name` attribute to control checkable exclusivity, then
we'd still need a grouping element like `<fieldset>`.

NOTE: `<fieldset>` is a more general grouping element than `<optgroup>`, which we briefly
considered, but decided against since it is used for grouping options in select elements, and should
stay that way.


### Are radio and checkbox menu items allowed as direct children of a `<menubar>`?

Currently, we don't see a need for this. All menuitems inside a menubar should perform some action
like opening a sub `<menulist>`, however we will reconsider this restriction if good use cases
arise, however these use cases are probably best solved with the
[`<toolbar>` proposal](https://open-ui.org/components/toolbar.explainer/).

For example, a text editor might use a `<menubar>` to provide basic font style adjustments. While it
might seem reasonable to use checkable `<menuitem>` elements to style content as "Bold", "Italic" or
"Underlined", the [`<toolbar>` proposal](https://open-ui.org/components/toolbar.explainer/) is more
apt to satisfy this use case.


### What's the difference between `<select>` and these new menu elements?

Like `<select>`, the menu element we propose offer a list of choices to pick from, and with
customizable select now available, users might be confused when to use which one.

The `<select>` element is a form-associated element containing `<option>` elements. Each of these
options must have a server-readable value. As a user chooses an option, specific events are
triggered (change, input) and a new value is set.

On the other hand, our proposed menu elements display a list of commands/actions that carry an
entirely different semantic meaning, along with a keyboard interaction model that generally adheres
to the
[ARIA guidelines for the menu and menubar pattern](https://www.w3.org/WAI/ARIA/apg/patterns/menubar/),
allowing users to traverse through deeply nested menu lists. Each menu item is a command that is
activatable, and can open a new/nested menulist or to trigger a specific command.


### Why are we adding `<menuitem>` and not re-using the `<command>` element?

See `<command>` element’s deprecated specification
[here](https://udn.realityripple.com/docs/Web/HTML/Element/command). In the last year, the command
and commandfor attributes were introduced so buttons can perform actions on other elements
declaratively. We thought re-using this obsolete element with the same name would be confusing to
developers.

Additionally, command is a single element, where as this proposal is introducing various elements
with additional grouping semantics and keyboard behaviors beyond what a single 'command' element
would represent - or reasonably be capable of creating parity with the various ARIA roles these new
proposed elements would be natively introducing to HTML.

### Popover semantics for `<menulist>`

Given a `<menuitem>` inside a `<menubar>`, it can invoke a `<menulist>` by invoking a target.

This can be accomplished by either:

* **`<menuitem command="show-popover" commandfor=id>`**
* **`<menuitem command="show-menu" commandfor=id>`**
    * We should allow [command invokers](https://open-ui.org/components/invokers.explainer/).
    * Useful for menu items that invoke custom commands.
    * Useful for interest invoker targets.
    * Useful to show modal dialog.
    * To decide: Does this make sense for radio/checkbox menuitems? Do we have use cases of a menuitem that toggles its checked state and invoke a behavior at the same time?
* Nest the menulist as a sibling of other menuitems, inside the parent menulist.

**Questions**
* Should `<menulist>` be a popover by default?
    * Yes, the popover attribute is not necessary. A menulist is by default a popover with value auto.
* Since `<menulist>`s are popovers by default, what happens if we add a popover attribute on top of it?
    * It can be specified to overwrite the `popover=auto` default and to set to `popover=hint` or `popover=manual`.
* Should menulist.showPopover() be the way to open these from script?
    * Yes (for now).

### Why are we using popover instead of openable for `<menulist>`?

An "[openable](https://open-ui.org/components/openable.explainer/)" is an element rendered in-page with display:none until it is opened. This could be useful for mobile apps, where the menubar is shown vertically in-page.

An element with `role=menu` is most commonly rendered as a popover. If someone wanted an in-page menu, then a menubar or fieldset of controls may be more appropriate. Though, if one wanted to show/hide a grouping of `<menuitem>` elements within a `<menulist>` popover, rather than as an adjacent submenu popover, then the following could be done:

```html
<menulist>
  ...
  <menuitem command="toggle-openable" commandfor="o">Colors</menuitem>
  <fieldset aria-label=colors openable id=o>
    <!-- grouped menuitems go here -->
  </fieldset>
</menulist>
```

Someone *could* show/hide a menubar - much like how Google docs allows one to show/hide the menubar with the toggle on the right side of the toolbar (hide the menus (ctrl+shift+f) button).

Openable is currently not standard. If there are valid cases of needing the `<menulist>` element to be in-page and the feature is mature enough, we can revisit this.


### Should clicking/activating a menuitem close the menu by default?

When user clicks on a menuitem:

1. If it has a valid reference to a menulist:
    1. If menulist is open, close the menulist (and all its nested menulist children).
    2. Else, open it and move focus.
2. Else, if menuitem is contained inside an open menulist, close its parentMenulist.

The algorithm when the user activates a `<menuitem>` in a `<fieldset checkable=multiple>`:

1. Set it to checked.

The algorithm when the user activates a `<menuitem>` in a `<fieldset checkable=single>`:

1. Set it to checked.
2. Set all other radio menu items in the same group to unchecked.

**Questions**

* Should there be an attribute to control this behavior?
* Should "focusout" on a `<menulist>` cause it to close?
* What about hovering on `<menuitem>`? This is not supported for popovers yet.
* Define the click and drag behavior.
* Define the activation behavior.
* Define the behavior for nested list cases. We can leverage that menulist are popovers, meaning the focus is scoped already.


### Should any of these elements be form-associated?

No. the menu elements proposal is intended to be semantically different from customizable `<select>`, which is in part achieved by the difference in form-association support. Supporting form-assocation also increases complexity (it raises questions like: what do we do if some of the controls appear *outside* of the menu element tree? how does form-association integrate with menu nesting?) with no obvious benefit; until a strong use case materializes, our default will be to not form-associate elements in this proposal.

However, we do recognize there are use cases where users might want to have inputs inside the menulists or menubars. For example, searchable menus using an input element. In such cases, the control is allowed in the menulist or menubar, but is not associated with a form.


### How can users customize the UI of these menu elements with CSS?

We propose these elements should not support the CSS appearance property and just have a "base" appearance by default like the `<dialog>` element.

**Questions**

* `<menubar>` should list `<menuitem>`s horizontally, but support using CSS writing-mode.
    * Can have vertical case by:
        * Set CSS `writing-mode: vertical-lr` on the `<menubar>`
        * Set CSS `writing-mode: horizontal-tb` on the `<menuitem>` inside the `<menubar>`
* `<menulist>` can support more than top to bottom layout:
    * Set CSS `display: grid` and use rows/columns.
* For checkable `<menuitem>`, should the check mark be on the left or the right?
    * Default should be on the left.
    * This can depend on the CSS `direction` property.
* For `<menuitem>`, should there be a default slot for the icon? If so, should it be on the left or the right?
    * Default should be on the left.
    * This can depend on the CSS `direction` property.


### There was a proposal for a Context Menu years ago. How is this different?

Previously, "context menus" were specified to allow developers to define custom context menus declaratively. This was being prototyped by Mozilla. Blink also had an implementation behind a flag.

```html
<menu id="menu1" type="context">
  <a href=#>Cancel</a>
</menu>

<button contextmenu="menu1">Right-click me</button>
```

Per [comment](https://github.com/whatwg/html/issues/2929#issuecomment-322804888) and [PR](https://github.com/whatwg/html/pull/2742), this feature was removed from the HTML specification because there was a lack of active interest by at least two implementers.

From Chromium, the [reasoning for removing support](https://issues.chromium.org/issues/40589971#comment65) was:

1. There is doubt whether the API is well designed.
2. This was considered a low priority because "reaching outside the content area and contributing items to the browser’s context menu" is a new capability and needs thorough designing. There was no bandwidth for new capabilities work.
3. This is not an interoperability priority (only existed in Firefox)

Chromium bug: [https://issues.chromium.org/issues/40589971](https://issues.chromium.org/issues/40589971)

Mozilla bug: [https://bugzilla.mozilla.org/show_bug.cgi?id=617528](https://bugzilla.mozilla.org/show_bug.cgi?id=617528)

Mozilla bug to remove support: [https://bugzilla.mozilla.org/show_bug.cgi?id=1372276](https://bugzilla.mozilla.org/show_bug.cgi?id=1372276)

Webkit bug about the touch bar API: [https://bugs.webkit.org/show_bug.cgi?id=179020](https://bugs.webkit.org/show_bug.cgi?id=179020)

The specification were removed per:

[https://github.com/whatwg/html/pull/2742](https://github.com/whatwg/html/pull/2742)

[https://github.com/whatwg/html/pull/2342](https://github.com/whatwg/html/pull/2342)

[https://github.com/whatwg/html/pull/244](https://github.com/whatwg/html/pull/244)


### How can we use menu elements to support custom right click Context Menus?

We discourage users from using these new elements to build a custom context menu. There are good reasons to keep the user agent defined context menu. For example, it allows users to copy/paste consistently across sites and to have browser extension options added. We do not plan to provide a declarative way to build a context menu.

However, this proposal is not about removing the existing web capabilities. Authors can use Javascript to add an event listener on "contextmenu" and call preventDefault to not show the default context menu. They can support custom context menus (similar to Google Doc) by showing a `<menulist>` at the cursor location.

We understand it would be helpful to have this feature be natively supported. If we want to open the conversation about supporting this, here are some open questions to resolve:

* What should be the keyboard behavior?
* What are the accessibility mappings? See open [ARIA issue](https://github.com/w3c/aria/issues/1971).
* Can we add support to add individual `<menuitem>` to the existing UA context menu?
* How can we keep the OS context menu’s style?
* Before we can support this, we need to fix [this](https://github.com/whatwg/html/issues/10905) popover bug about values auto vs manual.


### How does this proposal relate to navigation menus?

Navigation menus allow users to access different pages or sub-pages of a web application. They
commonly appear in a few different forms:

 - The `<nav>` element, which implicitly exposes the ARIA landmark
   [`navigation`](https://w3c.github.io/aria/#navigation) role.
    - Since hyperlinks and buttons are commonly children of this sort of navigation menu, authors
      generally do not need to declare specific ARIA roles to be accessible, and users can rely on
      standard <kbd>Tab</kbd> keey navigation to reach each interactive navigation element.
 - The abused [Navigation Menubar Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/menubar/examples/menubar-navigation/)
    - These generally have poor accessibility characteristics, and are not recommended.
 - The [Disclosure Navigation Menu Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/)
    - The APG describes this as a better alternative to the navigation menubar pattern above.

In [Issue #1193](https://github.com/openui/open-ui/issues/1193) we discussed the possibility of
supporting the Navigation Menubar Pattern with our proposal, and primarily due to accessibility
concerns, ultimately resolved not support it. Conceretely, this means that our proposal will
discourage the use of embedding `<a>` hyperlinks in menus alongside menuitems, likely through the
content model and default styles.

Page navigation can still be triggered with menu items, but will have to be done so with JavaScript
event listeners that handle the activation of the menu item, and do something like `location.href =
foo;` in response. We expect that this will result in our menu elements not being used as primary
navigation components on web pages; rather navigation menu items as we just described will be
one-offs, much like the following "Training" example, which opens a new page upon activation, but
does not need to be enumerated as anything other than an application menu item by screen readers:

<img width="400" src="/images/google-docs-training.png" alt="a menu item that triggers a page navigation manually upon activation" />

To support something similar to the Disclosure Navigation Menu Pattern, a new OpenUI proposal will
be formed, introducing something like a `<navigationbar>` element which is the navigation analogue
to our proposal's `<menubar>`, and has the right keyboard interaction model out-of-the-box.


### How can we use menu elements to support Touch Bar?

There is a history of attempting to do this in Webkit, for example for a
[Touch Bar](https://github.com/whatwg/html/issues/3251). The idea is to collect all your "commands"
and put them into the macOS menu bar (or expose them some other way). Our proposal does not address
this use case.


## Examples in code

### Google Docs: nested menulist

<img width="400" src="/images/menubar-google-docs.png" alt="menubar example" />

```html
<menubar>
 <menuitem command="show-menu" commandfor="format">Format</menuitem>
 <menuitem command="show-menu" commandfor="tools">Tools</menuitem>
 <menuitem command="show-menu" commandfor="extensions">Extensions</menuitem>
</menubar>

<menulist id="format">
  <menuitem command="show-menu" commandfor="text-format-menu">Text</menuitem>
  <menuitem command="show-menu" commandfor="paragraph-format-menu">Paragraph styles</menuitem>
  <menuitem command="show-menu" commandfor="align-format-menu">Align & indent</menuitem>
</menulist>

<menulist id="text-format-menu">
  <fieldset checkable="multiple">
    <menuitem id="bold-menuitem">Bold</menuitem>
    <menuitem>Italic</menuitem>
    <menuitem>Underline</menuitem>
  </fieldset>
</menulist>

<script>
document.querySelector('#bold-menuitem').addEventListener("click", () => {
  // Toggle bold-ness.
  if (text.style.fontWeight === 'normal') {
    text.style.fontWeight = 'bold';
  } else {
    text.style.fontWeight = 'normal';
  }
});
</script>
```

## Future enhancements

We envision more advanced capabilities in the future that could enhance the usability of the menu
elements designed in this explainer, but that are not necessarily in scope for our initial
proposal.

One such capability is keyboard shortcuts to invoke `<menuitem>` commands; see
https://github.com/openui/open-ui/issues/1225. We envision that this could be provided by a more
advanced version of the
[`accesskey`](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/accesskey)
primitive, that would provide customizable key commands that apply outside the scope of our
proposal.

## Reading List

Menus have been heavily discussed, please see below to learn about the existing specification and efforts.

### ARIA guidelines
- the ARIA [menu role](https://w3c.github.io/aria/#menu)
- the ARIA [menubar role](https://w3c.github.io/aria/#menubar)
- the ARIA [menuitem role](https://w3c.github.io/aria/#menuitem)
- the ARIA [menuitemcheckbox role](https://w3c.github.io/aria/#menuitemcheckbox)
- the ARIA [menuitemradio role](https://w3c.github.io/aria/#menuitemradio)
- the [Core AAM mappings](https://www.w3.org/TR/core-aam-1.2/#role-map-menu)
- the [HTML AAM for &lt;menu>](https://www.w3.org/TR/html-aam-1.0/#el-menu)

### Relevant ARIA issues
- [ARIA] [Consider allowing combobox to open menus](https://github.com/w3c/aria/issues/2050)

### Relevant Navigation specific issues
- [ARIA practices] [Clarify Purpose of Menu Navigation](https://github.com/w3c/aria-practices/issues/353)
- [OpenUI] [Navigation vs menu items use case](https://github.com/openui/open-ui/issues/1193)
- [ARIA] [Concerning navigation "menus" (open ui related)](https://github.com/w3c/aria/issues/2510)

### APG pattern recommendations (note these are not guidelines)
- [menu button](https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/)
- [menubar](https://www.w3.org/WAI/ARIA/apg/patterns/menubar/)
  - [menubar example](https://www.w3.org/WAI/ARIA/apg/patterns/menubar/examples/menubar-editor/)
  - [menubar navigation example](https://www.w3.org/WAI/ARIA/apg/patterns/menubar/examples/menubar-navigation/)
- [disclosure](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/)
  - [disclosure navigation menu example](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/)
  - [disclosure navigation menu with top-level links example](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation-hybrid/)
- [toolbar](https://www.w3.org/WAI/ARIA/apg/patterns/toolbar/)

### HTML specification
- The [menu element](https://html.spec.whatwg.org/multipage/grouping-content.html#the-menu-element)
- The [nav element](https://html.spec.whatwg.org/multipage/#the-nav-element)

### HTML specification for previous efforts
- The [obsoleted menuitem element](https://html.spec.whatwg.org/multipage/obsolete.html#menuitem)
- The [obsoleted type attribute on menu element](https://html.spec.whatwg.org/multipage/obsolete.html#attr-menu-type)

### Blog posts from accessibility community
- https://www.scottohara.me/blog/2021/10/21/menu.html
- https://adrianroselli.com/2017/10/dont-use-aria-menu-roles-for-site-nav.html
- https://adrianroselli.com/2019/06/link-disclosure-widget-navigation.html
- https://adrianroselli.com/2023/05/be-careful-using-menu.html

### Blog posts for Design System
- https://webflow.com/blog/navigation-bar-design
- https://developer.apple.com/design/human-interface-guidelines/the-menu-bar

## Issues / Discussions

This section links to all of the relevant discussions and [issues](https://github.com/openui/open-ui/issues?q=is%3Aissue%20state%3Aopen%20label%3Amenu) related to `menu`:

### OpenUI
- [Menu elements proposal](https://github.com/openui/open-ui/issues/1179)
- [Explicitly mention whether reading-flow should impact arrow key navigation](https://github.com/openui/open-ui/issues/1187)
- [improve distinction between menubar and toolbar](https://github.com/openui/open-ui/issues/1188)
- [How should we group checkboxes and radios, and how should we decide if they are checkboxes or radios?](https://github.com/openui/open-ui/issues/1189)
- [Activation behavior for opening submenus](https://github.com/openui/open-ui/issues/1190)
- [Explicitly mention support for HR as a separator](https://github.com/openui/open-ui/issues/1191)
- [When should activating a menuitem close the menu?](https://github.com/openui/open-ui/issues/1192)
- [Navigation vs menu items use case](https://github.com/openui/open-ui/issues/1193)
- [Consider reusing `<menu>` and `<nav>` HTML elements](https://github.com/openui/open-ui/issues/1194)
- [allow buttons to open menu(list) popups](https://github.com/openui/open-ui/issues/1196)
- [[openable] allow author choice of opening a submenu inline or as a popup](https://github.com/openui/open-ui/issues/1198)
- [do we *need* to introduce menuitem elements?](https://github.com/openui/open-ui/issues/1200)
- [define orientation attribute](https://github.com/openui/open-ui/issues/1201)
- [Define a default checked attribute for menuitem](https://github.com/openui/open-ui/issues/1205)
- [Keyboard shortcuts?](https://github.com/openui/open-ui/issues/1225)
- [Should menulist be a popover by default?](https://github.com/openui/open-ui/issues/1226)
